
using System;

public static class Program
{
    private const string template_parameter = "T";
    private const string public_accessmodifier = "Public";
    private static void w(string a)
    {
        Console.WriteLine(a);
    }

    private static void w()
    {
        Console.WriteLine();
    }

    private static string strcat(params string[] s)
    {
        string r = null;
        for(int i = 0; i < s.Length; i++)
            r += s[i] + "\r\n";
        return r;
    }

    private class arguments
    {
        private const string tp = "t:";
        private const string ocp = "oc:";
        private const string ocam = "ocam:";
        private const string nsp = "ns:";
        private const string cam = "cam:";
        private const string ntp = "ntp:";
        private const string pp = "pp:";
        public readonly string type;
        public readonly string outter_class;
        public readonly string outter_class_accessmodifier;
        public readonly string namespaces;
        public readonly string class_accessmodifier;
        public readonly bool is_not_template_parameter;
        public readonly bool is_plugin;

        public arguments(string[] args)
        {
            type = template_parameter;
            outter_class = null;
            outter_class_accessmodifier = public_accessmodifier;
            namespaces = null;
            class_accessmodifier = public_accessmodifier;
            is_not_template_parameter = false;
            is_plugin = false;
            if(args != null)
            {
                for(int i = 0; i < args.Length; i++)
                {
                    if(!string.IsNullOrEmpty(args[i]))
                    {
                        if(args[i].StartsWith(tp))
                        {
                            type = args[i].Substring(tp.Length);
                        }
                        else if(args[i].StartsWith(ocp))
                        {
                            outter_class = args[i].Substring(ocp.Length);
                        }
                        else if(args[i].StartsWith(ocam))
                        {
                            outter_class_accessmodifier = args[i].Substring(ocam.Length);
                        }
                        else if(args[i].StartsWith(nsp))
                        {
                            namespaces = args[i].Substring(nsp.Length);
                        }
                        else if(args[i].StartsWith(cam))
                        {
                            class_accessmodifier = args[i].Substring(cam.Length);
                        }
                        else if(args[i].StartsWith(ntp))
                        {
                            is_not_template_parameter = true;
                        }
                        else if(args[i].StartsWith(pp))
                        {
                            is_plugin = true;
                        }
                    }
                }
            }
        }

        public bool template_type
        {
            get
            {
                return type == template_parameter && (!is_not_template_parameter);
            }
        }
    }

    private static string class_name(arguments a)
    {
        if(a.is_plugin) return a.outter_class;
        else return "adaptive_array" + (a.template_type ? "(Of " + a.type + ")" : "_" + a.type.ToLower());
    }

    public static void Main(string[] args)
    {
        arguments a = new arguments(args);
        w("\'this file is generated by /osi/root/codegen/adaptive_array/adaptive_array.exe");
        w("\'so change /osi/root/codegen/adaptive_array/adaptive_array.cs instead of this file");
        w("\'usually you do not need to use this codegen and the code generated unless it's in a very strict performance related code");
        w("\'use vector is a better way, while the implementation of vector is also using the code generated by this codegen");
        w("\'p.s. this file needs to work with osi.root.connector project");
        w();
        w("Imports osi.root");
        w("Imports osi.root.connector");
        w("Imports osi.root.constants");
        w();
        if(!string.IsNullOrEmpty(a.namespaces))
        {
            w("Namespace " + a.namespaces);
        }

        if(!string.IsNullOrEmpty(a.outter_class))
        {
            w("Partial " + a.outter_class_accessmodifier + " Class " + a.outter_class);
        }

        if(!a.is_plugin)
        {
            w(a.class_accessmodifier + " Class " + class_name(a));
        }
        w(strcat(
"    Implements ICloneable, IComparable(Of " + class_name(a) + "), IComparable",
"",
"    Private Const size_limitation As UInt32 = (max_uint32 >> 1)",
"    Private Shared ReadOnly default_value As " + a.type + " = Nothing",
"",
"    Private Shared Function expected_capacity(ByVal n As UInt32) As UInt32",
"        If n <= 2 Then",
"            Return 4",
"        Else",
"            Return n << 1",
"        End If",
"    End Function",
"",
"    Private d() As " + a.type,
"    Private s As UInt32",
"",
"    Public Sub New()",
"    End Sub",
"",
"    Public Sub New(ByVal n As UInt32)",
"        reserve(n)",
"    End Sub",
"",
"    Private Sub New(ByVal d() As " + a.type + ", ByVal s As UInt32)",
"        Me.d = d",
"        Me.s = s",
"    End Sub",
"",
"    Public Shared Function move(ByVal that As " + class_name(a) + ") As " + class_name(a),
"        If that Is Nothing Then",
"            Return Nothing",
"        Else",
"            Dim r As " + class_name(a) + " = Nothing",
"            r = New " + class_name(a) + "()",
"            move_to(that, r)",
"            Return r",
"        End If",
"    End Function",
"",
"    Protected Shared Sub move_to(ByVal this As " + class_name(a) + ", ByVal that As " + class_name(a) + ")",
"        k_assert(Not this Is Nothing)",
"        k_assert(Not that Is Nothing)",
"        that.d = this.d",
"        that.s = this.s",
"        this.d = Nothing",
"        this.s = 0",
"    End Sub",
"",
"    Public Shared Function swap(ByVal this As " + class_name(a) + ", ByVal that As " + class_name(a) + ") As Boolean",
"        If this Is Nothing OrElse that Is Nothing Then",
"            Return False",
"        Else",
"            connector.swap(this.d, that.d)",
"            connector.swap(this.s, that.s)",
"            Return True",
"        End If",
"    End Function",
"",
"    Public Function clone() As " + class_name(a),
"        Dim r As " + class_name(a),
"        r = New " + class_name(a),
"        clone_to(Me, r)",
"        Return r",
"    End Function",
"",
"    Protected Shared Sub clone_to(ByVal this As " + class_name(a) + ", ByVal that As " + class_name(a) + ")",
"        k_assert(Not this Is Nothing)",
"        k_assert(Not that Is Nothing)",
"        that.resize(this.size())",
"        If Not this.empty() Then",
"            For i As UInt32 = 0 To CUInt(this.size() - 1)",
"                copy(that.d(i), this.d(i))",
"            Next",
"        End If",
"    End Sub",
"",
"    Public Function max_size() As UInt32",
"        Return size_limitation",
"    End Function",
"",
"    Public Function data() As " + a.type + "()",
"        Return d",
"    End Function",
"",
"    Default Public Property at(ByVal p As UInt32) As " + a.type,
"        Get",
"            Return d(p)",
"        End Get",
"        Set(ByVal value As " + a.type + ")",
"            d(p) = value",
"        End Set",
"    End Property",
"",
"    Public Function [get](ByVal p As UInt32) As " + a.type,
"        Return d(p)",
"    End Function",
"",
"    Public Sub [set](ByVal p As UInt32, ByVal v As " + a.type + ")",
"        d(p) = v",
"    End Sub",
"",
"    Public Function size() As UInt32",
"        Return s",
"    End Function",
"",
"    Public Function empty() As Boolean",
"        Return size() = 0",
"    End Function",
"",
"    Public Function capacity() As UInt32",
"        Return array_size(d)",
"    End Function",
"",
"    Public Function back() As " + a.type,
"        Return d(size() - uint32_1)",
"    End Function",
"",
"    Public Sub clear()",
"        If size() > 0 Then",
"            memclr(d, 0, s)",
"            s = 0",
"        End If",
"    End Sub",
"",
"    Public Sub push_back(ByVal v As " + a.type + ")",
"        reserve(size() + uint32_1)",
"        d(size()) = v",
"        s += uint32_1",
"    End Sub",
"",
"    Public Sub pop_back()",
"        s -= uint32_1",
"        d(size()) = default_value",
"    End Sub",
"",
"    Public Sub reserve(ByVal n As UInt32)",
"        If capacity() < n Then",
"            If empty() Then",
"                ReDim d(expected_capacity(n) - uint32_1)",
"            Else",
"                ReDim Preserve d(expected_capacity(n) - uint32_1)",
"            End If",
"        End If",
"    End Sub",
"",
"    Public Sub resize(ByVal n As UInt32)",
"        If capacity() < n Then",
"            reserve(n)",
"        ElseIf size() > n Then",
"            memclr(d, n, size() - n)",
"        End If",
"        s = n",
"    End Sub",
"",
"    Public Sub resize(ByVal n As UInt32, ByVal v As " + a.type + ")",
"        Dim os As UInt32 = 0",
"        os = size()",
"        If n > os Then",
"            resize(n)",
"            memset(d, os, n - os, v)",
"        Else",
"            resize(n)",
"        End If",
"    End Sub",
"",
"    Public Sub shrink_to_fit()",
"        If empty() Then",
"            ReDim d(-1)",
"        ElseIf capacity() > size() Then",
"            ReDim Preserve d(size() - uint32_1)",
"        End If",
"    End Sub",
"",
"    Public Function ICloneable_Clone() As Object Implements ICloneable.Clone",
"        Return clone()",
"    End Function",
"",
"    Public Shared Function compare(ByVal this As " + class_name(a) + ", ByVal that As " + class_name(a) + ") As Int32",
"        Dim c As Int32 = 0",
"        c = object_compare(this, that)",
"        If c = object_compare_undetermined Then",
"            k_assert(Not this Is Nothing)",
"            k_assert(Not that Is Nothing)",
"            If this.size() < that.size() Then",
"                Return -1",
"            ElseIf this.size() > that.size() Then",
"                Return 1",
"            Else",
"                Return memcmp(this.d, that.d, this.size())",
"            End If",
"        Else",
"            Return c",
"        End If",
"    End Function",
"",
"    Public Function CompareTo(ByVal obj As Object) As Int32 Implements IComparable.CompareTo",
"        Return CompareTo(cast(Of " + class_name(a) + ")(obj, False))",
"    End Function",
"",
"    Public Function CompareTo(ByVal other As " + class_name(a) + ") As Int32 Implements IComparable(Of " + class_name(a) + ").CompareTo",
"        Return compare(Me, other)",
"    End Function"
        ));

        if(!a.is_plugin)
        {
            w("End Class");
        }

        if(!string.IsNullOrEmpty(a.outter_class))
        {
            w("End Class");
        }

        if(!string.IsNullOrEmpty(a.namespaces))
        {
            w("End Namespace");
        }
    }
}

